import { HashMap } from "../../api/struct/HashMap";
import { E_GameBaseAttr } from "../defs/com/E_GameBaseAttr";
import { E_LordGlobal } from "../defs/lord/E_LordGlobal";
import { E_PetBelongType } from "../defs/pet/E_PetBelongType";
import { E_PlayerIncID } from "../defs/player/E_PlayerIncID";
import { E_TrainPos } from "../defs/train/E_TrainPos";
import { CDEquipment } from "../excel/CDEquipment";
import { CDEquipmentSuit, E_CDEquipmentSuit } from "../excel/CDEquipmentSuit";
import { CDLordGlobal } from "../excel/CDLordGlobal";
import { CDLordTalent } from "../excel/CDLordTalent";
import { CDLordTraining, E_CDLordTraining } from "../excel/CDLordTraining";
import { CDMath } from "../excel/CDMath";
import { CDPet } from "../excel/CDPet";
import { CDSkill } from "../excel/CDSkill";
import { CDUnitLv } from "../excel/CDUnitLv";
import { CEMath } from "../excel_extend/CEMath";
import { Equip } from "../struct/Equip";
import { Player } from "../struct/Player";
import { SDBattle } from "./SDBattle";
import { SDEquip } from "./SDEquip";
import { SDHuangXiaoxi } from "./SDHuangXiaoxi";
import { SDPet } from "./SDPet";
import { SDPray } from "./SDPray";
import { SDSkill } from "./SDSkill";
import { SDSuits } from "./SDSuits";
import { SDTalent } from "./SDTalent";

/**
 * 数据-角色
 */
export abstract class SDPlayer {

    /**表名 */
    public static readonly REDIS_MAP_NAME = 'PLAYER_MAP';


    /**
     * 获取玩家spine
     * @returns 
     */
    public static getSpineUrl(player: Player): string {
        return 'role_01/role_01';
    }


    /**
     * 玩家战力
     * @param player 
     * @returns 
     */
    public static getFightScore(player: Player): number {

        const skillIdLevels = this.getPlayerSkillIdLevels(player, []);
        const list = this.getPlayerAttrs(player, skillIdLevels, [], E_PetBelongType.Fight);
        const score = SDBattle.getFightScore(list);

        return Math.floor(score);
    }


    /**
     * 查找对应配置id的装备
     * @param player 
     * @param configID 
     * @param justExist 
     * @param isWearOn 
     * @returns 
     */
    public static getEquipByConfigID(player: Player, configID: number, justExist = true, isWearOn = true): Equip[] | Equip | boolean {
        const equipConfig = CDEquipment.getData(configID);
        if (!equipConfig) {
            return justExist ? false : null;    //无配置
        }

        if (isWearOn) {
            const wearID = player.equipManager.getWear(equipConfig.group);
            if (!wearID) {
                return justExist ? false : null;    //没穿
            }

            const equip = player.equipManager.getEquip(wearID);
            if (configID !== equip.configId) {
                return justExist ? false : null;    //不一致
            }
            else {
                return justExist ? true : equip;    //穿了
            }
        }
        else {
            const vs = player.equipManager.getEquipValues();
            let list: Equip[] = null;

            for (let i = vs.length - 1; i >= 0; i--) {
                const equip = vs[i];
                if (configID !== equip.configId) {
                    continue;
                }
                if (justExist) {
                    return true;
                }
                if (!list) {
                    list = [];
                }
                list.push(vs[i]);
            }
            return justExist ? false : list;
        }
    }


    /**套装缓冲 */
    private static readonly GET_SUIT_MAP_TMP = new HashMap<number, number[]>();

    /**
    * 获取技能
    * @param player 
    * @param outList 
    * @returns 
    */
    public static getPlayerSkillIdLevels(
        player: Player,
        outList: number[] = []
    ): number[] {

        //普攻
        {
            //TODO 给角色一个普通攻击的技能
            outList.push(CDSkill.datas.getValues()[0].id, player.playerInfo.level);
        }

        //天赋
        {
            const ks = player.talent.getTalentLevelKeys();
            const vs = player.talent.getTalentLevelValues();
            for (let i = ks.length - 1; i >= 0; i--) {
                const config = CDLordTalent.getData(ks[i]);
                if (config && config.skillid > 0) {
                    outList.push(config.skillid, vs[i]);
                }
            }
        }

        //上阵宠物
        {
            const ks = player.petManager.getFightingKeys();
            for (let i = 0, len = ks.length; i < len; i++) {
                const pet = player.petManager.getPet(ks[i]);
                if (!pet) {
                    continue;
                }
                const config = CDPet.getData(pet.configId);
                if (!config) {
                    continue;
                }

                const skillList = config.passiveSkill;
                for (let j = 0, slen = skillList.length; j < slen; j++) {
                    if (skillList[j] > 0) {
                        outList.push(skillList[j], 1);    //TODO 被动技能默认1级，需要后续修改
                    }
                }
            }
        }

        //装备
        {
            const wearIDs = player.equipManager.getWearValues();
            for (let i = wearIDs.length - 1; i >= 0; i--) {
                const equip = player.equipManager.getEquip(wearIDs[i]);
                const equipConfig = SDEquip.getEquipConfig(equip);
                if (equipConfig && equipConfig.skill > 0) {
                    outList.push(equipConfig.skill, 1);   //TODO 被动技能默认1级，需要后续修改
                }
            }
        }
        // ... existing code ...
        // {
        //     //装备
        //     const ks = player.equipManager.getWearKeys();
        //     const vs = player.equipManager.getWearValues();
        //     for (let i = ks.length - 1; i >= 0; i--) {
        //         const equip = player.equipManager.getEquip(vs[i]);
        //         if (!equip) {
        //             continue;
        //         }
        //         const partLevel = player.equipManager.getPartLevel(ks[i]) || 1; // 默认1级
        //         SDEquip.getEquipAttrByPartLevel(
        //             equip,
        //             partLevel,
        //             outList
        //         );
        //     }
        // }
        // ... existing code ...

        //黄小西被动技能 - 所有已解锁的黄小西被动技能都生效
        // {
        //     if (player.huangXiaoxiManager) {
        //         const allHuangXiaoxi = player.huangXiaoxiManager.getHuangXiaoxiListValues();

        //         for (let i = 0; i < allHuangXiaoxi.length; i++) {
        //             const huangXiaoxi = allHuangXiaoxi[i];
        //             if (huangXiaoxi && huangXiaoxi.isUnlocked) {
        //                 const config = CDHuangXiaoxi.getData(huangXiaoxi.huangXiaoxiId);
        //                 if (config && config.passiveSkill) {
        //                     for (let j = 0, slen = config.passiveSkill.length; j < slen; j++) {
        //                         if (config.passiveSkill[j] > 0) {
        //                             // 被动技能等级根据好感度等级决定
        //                             // 从好感度配置表获取最大等级
        //                             const favorConfigs = CDHuangXiaoxiFavor.datas.getValues();
        //                             let maxFavorLevel = 10; // 默认最大等级
        //                             for (let k = 0; k < favorConfigs.length; k++) {
        //                                 if (favorConfigs[k].id > maxFavorLevel) {
        //                                     maxFavorLevel = favorConfigs[k].id;
        //                                 }
        //                             }
        //                             const skillLevel = Math.min(huangXiaoxi.favorLevel, maxFavorLevel);
        //                             outList.push(config.passiveSkill[j], 1);
        //                         }
        //                     }
        //                 }
        //             }
        //         }
        //     }
        // }

        //套装
        {
            const suits = SDSuits.getWearSuits(player, this.GET_SUIT_MAP_TMP);
            const ks = suits.getKeys();
            const vs = suits.getValues();
            for (let i = 0, len = ks.length; i < len; i++) {
                const suitWearLen = vs[i].length;
                const suitConfig = CDEquipmentSuit.getData(ks[i]);
                for (let j = E_CDEquipmentSuit.skill_1; j <= E_CDEquipmentSuit.skill_3; j++) {
                    if (SDSuits.isSuitSkillOpen(suitConfig, j - E_CDEquipmentSuit.skill_1, suitWearLen)) {
                        const skillID = suitConfig.getAttr(j);
                        outList.push(skillID, 1);         //TODO 被动技能默认1级，需要后续修改
                    }
                }
            }
        }

        return outList;
    }


    /**
    * 获取玩家详细属性，含宠物
    * @param player 
    * @param skillIDLevels 
    * @param outList 
    * @param petBelongType
    * @returns 
    */
    public static getPlayerAttrs(
        player: Player,
        skillIDLevels: number[],
        outList?: number[],
        petBelongType = E_PetBelongType.Fight
    ): number[] {

        outList = this.getPlayerBaseAttrs(player, skillIDLevels, outList);

        switch (petBelongType) {
            case E_PetBelongType.Arena:
                {
                    const ks = player.arena.getPetKeys();
                    for (let i = ks.length - 1; i >= 0; i--) {
                        SDPet.addPetBaseAttrs(player, ks[i], outList);
                    }
                }
                break;

            default:
                {
                    const ks = player.petManager.getPetKeys();
                    for (let i = ks.length - 1; i >= 0; i--) {
                        SDPet.addPetBaseAttrs(player, ks[i], outList);
                    }
                }
                break;
        }

        return outList;
    }


    /**
     * * 获取玩家基础属性，此方法聚合了来自角色等级、天赋、装备等多个系统的基础属性。
     * @param player 玩家实例
     * @param skillIDLevels [输出] 技能ID和等级平铺的数组，格式为 [id1, lv1, id2, lv2, ...]
     * @param outList [输出] 聚合后的属性列表，数组下标对应 E_GameBaseAttr 枚举
     * @returns 返回聚合后的属性列表
     */
    public static getPlayerBaseAttrs(
        player: Player,
        skillIDLevels: number[],
        outList?: number[],
    ): number[] {

        outList = outList || [];
        outList.length = E_GameBaseAttr.EnumCount;
        for (let i = 0, len = E_GameBaseAttr.EnumCount; i < len; i++) {
            outList[i] = 0;
        }

        //基础
        {
            const unitLvConfig = CDUnitLv.getData(player.playerInfo.level);
            if (unitLvConfig) {
                this.addMathConfig(CDMath.getData(unitLvConfig.math), outList);
            }
        }

        //训练
        {
            const train = player.train;
            //单部位
            for (let i = 0; i < E_TrainPos.EnumCount; i++) {
                const lv = train.getLevel(i);
                const config = CDLordTraining.getData(lv);
                if (config) {
                    const mathID: number = config.getAttr(E_CDLordTraining.math_1 + i);
                    this.addMathConfig(CDMath.getData(mathID), outList);
                }

            }
            //共鸣
            const lv = CDLordGlobal.getData(E_LordGlobal.ResonateMath).value;
            this.addMathConfig(CDMath.getData(lv + train.resonate), outList);
        }

        //装备
        {
            const em = player.equipManager;
            const wearIDs = em.getWearValues();
            //获取部位
            // const partKeys = em.getWearKeys();
            for (let i = wearIDs.length - 1; i >= 0; i--) {
                const equip = em.getEquip(wearIDs[i]);
                //获取部位等级
                // const level = em.getPartLevel(partKeys[i]);
                SDEquip.addGameBaseAttr(equip, outList);
            }
        }
        SDHuangXiaoxi.addMath(player, outList);                     //黄小西
        SDPray.addMath(player, outList);                     //祝福
        SDTalent.addMath(player, outList);                   //天赋

        //其他待添加

        //技能增加的math
        if (skillIDLevels) {
            for (let i = 0, len = skillIDLevels.length; i < len; i += 2) {
                SDSkill.addGameBaseAttr(skillIDLevels[i], skillIDLevels[i + 1], outList, false);
            }
        }

        return outList;
    }


    /**
     * 添加属性值
     * @param config 
     * @param outList GameAttrType
     */
    public static addMathConfig(
        config: CDMath,
        outList: number[],
        ratio = 1
    ): void {
        if (!config || !outList) {
            return;
        }
        for (let i = 0, len = E_GameBaseAttr.EnumCount; i < len; i++) {
            const idx = CEMath.getExcelTypeByGameAttrType(i);
            outList[i] = (outList[i] || 0) + Math.floor(ratio * config.getAttr(idx));
        }
    }


    /**
    * 获取唯一性id
    * @param player 
    */
    public static getUniqueIndex(player: Player, type: E_PlayerIncID): number {
        const id = player.getIncId(type) + 1;
        player.putIncId(type, id);
        return id;
    }





}
